Shader "PJD/Role/Cartoon/Bronya/Bronya_C7_GZ/BronyaBody"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _MaskTex("MaskTex",2D) = "white" {}   // r  手臂护甲 鞋子 g 自阴影 b 皮质高光 a 衣服布料

        // 描边
        [Header(Outline)]
        _OutlineColor("OutlinneColor",Color) = (0,0,0,1)
        _OutlineColor2("OutlinneColor2",Color) = (0,0,0,1)
        _OutlineWidth("OutlineWidth",Range(0,1)) = 0.1
        _UniformWidth("UniformWidth",Range(0,1)) = 0.1 //

        // [Header(Color)]
        [Header(Diffuse)]
        _HColor("Highlight Color",Color) = (1,1,1,1)   //亮部颜色
        _HColor2("Highlight2 Color",Color) = (1,1,1,1)   //亮部颜色
        _SColor("shadow Color",Color) = (0.5,0.5,0.5,1)  //阴影部分颜色
        _RampThreshold("RampThreshold",Range(0,1)) = 0.8		//明暗边界阀值
        _RampSmooth("RampSmooth",Range(0,1)) = 0.1				// 明暗边界平滑过渡

        _ShadowValue("ShadowValue",Vector) = (1,1,1,1)
        _ShadowPower("ShadowPower",Vector) = (0.1,0.1,0.1,0.1)


        // 高光
        [Header(Specular)]
        _SpecularValue1("SpecularValue1",Vector) = (1,1,1,1) 
        _SpecularValue2("SpecularValue2",Vector) = (1,1,1,1)
        
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }

        // 描边
        Pass
        {
            Cull Front
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 color  : COLOR;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MaskTex;
            float _OutlineWidth;
            float4 _OutlineColor;
            float4 _OutlineColor2;
            float _UniformWidth;

            // 实际描边效果是有具体部分描边的，应该有用模型的切线存信息，颜色不是统一的
            // 断边有点严重，试图使用后处理描边
            v2f vert (appdata v)
            {
                v2f o;
                o.uv = v.uv;
                // 描边本身的宽度是不会变化的，但是随着时距会有近大远小的视觉效果
                // 如果需要保持不变，则需要根据时距的变化加上对应的值，则原来宽度+视距的长度，可表示效果
                // 求出相机与顶点之间的距离
                float3 worldPos = mul(unity_ObjectToWorld,v.vertex.xyz);
                float3 distance = length(_WorldSpaceCameraPos - worldPos);

                //distance = 1 时，保持近大远小
                //distance = distance 时，保持粗细不变
                // _UniformWidth = 0时，使用默认近大远小 ，否则保持粗细不变
                distance = lerp(1,distance,_UniformWidth);
                float3 pos = v.vertex.xyz;
                float3 width = normalize(v.normal) * _OutlineWidth *0.01;
                width *= distance;
                width *= v.color.a;  //模型的顶点色 a 控制模型描边的粗细
                v.vertex.xyz += width;
                
                o.vertex = UnityObjectToClipPos(v.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 maskTex = tex2D(_MaskTex,i.uv);
                return _OutlineColor2.a > maskTex.a ?_OutlineColor2:_OutlineColor;
            }
            ENDCG
        }

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"
            //#include "AutoLight.cginc"
            #include "Lighting.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
                float3 worldNormal : TEXCOORD2;
                float3 worldPos : TEXCOORD3;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _MaskTex;

            // 漫反射亮暗面颜色
            float4 _HColor;
            float4 _HColor2;
            float4 _SColor;
            float _RampThreshold;
            float _RampSmooth;
            float4 _ShadowValue;
            float4 _ShadowPower;

            // 高光
            float4 _SpecularValue1;
            float4 _SpecularValue2;
            

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.worldPos = mul(unity_ObjectToWorld,v.vertex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // 入射光
                float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
                // 法线
                float3 normalDirection = normalize(i.worldNormal);
                // 观察方向
                float3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
                // 半角向量
                float3 halfDirection = normalize(lightDirection + viewDirection);
                // 光照颜色
                float3 lightColor = _LightColor0.rgb;

                
                // sample the texture
                fixed4 mainTex = tex2D(_MainTex, i.uv);

                // r  手臂护甲 鞋子 皮革类高光 g 自阴影 b 皮质高光 a 衣服布料
                // r 和 b 的内容近似，b有高光更亮的部分， r 比 b整体更亮些 
                // maskTex.g 贴图阴影 必然要叠上去做阴影的 和 漫反射一起
                // a 都是布料部分，没有皮肤 区分皮肤和非皮肤的光照
                fixed4 maskTex = tex2D(_MaskTex,i.uv);

                //return maskTex.a;

                //============= 漫反射
                float NdotL = dot(normalDirection,lightDirection) * 0.5 + 0.5;
                
               
              
                // 明暗过渡
                fixed3 ramp = smoothstep(_RampThreshold - _RampSmooth * 0.5,_RampThreshold + _RampSmooth * 0.5,NdotL);           
    
                // // 阴影颜色
                fixed3 SColor = maskTex.a > 0.1 ?lerp(_HColor,_SColor,_SColor.a):lerp(_HColor2,_SColor,_SColor.a);
                // // 亮部颜色
                fixed3 HSColor =  maskTex.a > 0.1 ? _HColor.rgb : _HColor2.rgb ;
                ramp = lerp(SColor,HSColor,ramp);

                fixed3 diffuse = ramp * lightColor;// * (maskTex.g * _ShadowValue.r );

                // ao 自阴影
                fixed ramp2 = smoothstep(_ShadowValue.r,_ShadowValue.g,maskTex.g);
                ramp2 += _ShadowValue.b;
                ramp2 = saturate(ramp2);
                fixed3 ramp2Color = ramp2 > _ShadowPower.g?ramp2: ramp2 * _SColor * _ShadowPower.b; 

                fixed3 diffuseTex = 0;
                diffuseTex = maskTex.g * mainTex;
               // return fixed4(diffuseTex,1);
                
                //return fixed4(diffuse,1);
                // 自阴影
                //fixed3 shadowBody =  maskTex.g * SColor;
                //return fixed4(shadowBody,1);
                //============= 高光

                fixed NdotH = dot(normalDirection,halfDirection);
                fixed specular1 = _SpecularValue1.r *  maskTex.r * pow(NdotH,_SpecularValue1.g *  maskTex.b);
                specular1 = step(_SpecularValue1.b,specular1) * _SpecularValue1.a;

                fixed specular2 = _SpecularValue2.r *  maskTex.r * pow(NdotH,_SpecularValue2.g * maskTex.b);
                specular2 = step(_SpecularValue2.b,specular2) * _SpecularValue2.a;

                fixed3 specular =specular1 * mainTex +  specular2 * mainTex;
                // return fixed4(specular,1);
                
                fixed3 finalColor = mainTex;

                // 
                finalColor = _ShadowValue.a >= maskTex.a ? (finalColor + specular) * diffuse * ramp2Color:(finalColor + specular) * diffuse * ramp2Color * (maskTex.a * _ShadowPower.r );
              

              

                fixed4 finalRGBA = fixed4(finalColor,1);
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, finalRGBA);
                return finalRGBA;
            }
            ENDCG
        }
    }
}
